// gasp.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"


typedef struct {
    ULONG32  	version;
    USHORT 	numTables;
    USHORT 	searchRange; 
    USHORT 	entrySelector;
    USHORT 	rangeShift;
} offset_table;
typedef struct {
    ULONG  	tag;//  	4 -byte identifier.
    ULONG 	checkSum;// 	CheckSum for this table.
    ULONG 	offset;// 	Offset from beginning of TrueType font file.
    ULONG 	length;// 	Length of this table.
} table_record;
enum rangeGaspBehavior {
GASP_DOGRAY =0x0002,//	small sizes, typically ppem<9
GASP_GRIDFIT = 0x0001,// 	medium sizes, typically 9<=ppem<=16
GASP_SYMMETRIC_GRIDFIT =	0x0004,// 	typically always enabled
GASP_SYMMETRIC_SMOOTHING =	0x0008,// 	larger screen sizes, typically ppem>15, most commonly used with the gridfit flag.
};
typedef struct {
USHORT  	rangeMaxPPEM;// 	Upper limit of range, in PPEM
USHORT 	rangeGaspBehavior;// 	Flags describing desired rasterizer behavior.
}GASPRANGE;
typedef struct {
USHORT  	version;//  	Version number (set to 1)
USHORT 	numRanges;// 	Number of records to follow
GASPRANGE 	gaspRange[1];// 	Sorted by ppem
} gasp_table;
typedef struct {
ULONG  	version;// number  	0x00010000 for version 1.0.
ULONG 	fontRevision;// 	Set by font manufacturer.
ULONG 	checkSumAdjustment;// 	To compute: set it to 0, sum the entire font as ULONG, then store 0xB1B0AFBA - sum.
ULONG 	magicNumber;// 	Set to 0x5F0F3CF5.
}head_table;
char ttp[256];
char* ap(USHORT p) {
    ttp[0] = 0;
    if(p&GASP_GRIDFIT)
        strcat(ttp,"GASP_GRIDFIT(0x1) ");
    if(p&GASP_DOGRAY)
        strcat(ttp,"GASP_DOGRAY(0x2) ");
    if(p&GASP_SYMMETRIC_GRIDFIT)
        strcat(ttp,"GASP_SYMMETRIC_GRIDFIT(0x4) ");
    if(p&GASP_SYMMETRIC_SMOOTHING)
        strcat(ttp,"GASP_SYMMETRIC_SMOOTHING(0x8) ");
    return ttp;
}
ULONG
CalcTableChecksum(ULONG *Table, ULONG Length)
{
    ULONG Sum = 0L;
    ULONG *Endptr = Table+((Length+3) & ~3) / sizeof(ULONG);
    while (Table < Endptr){
        Sum += btoll(*Table);
        Table++;
    }
    return Sum;
}

int wmain(int argc, WCHAR* argv[])
{
    HANDLE f = CreateFile(argv[1],GENERIC_READ,FILE_SHARE_READ|FILE_SHARE_WRITE,0,OPEN_EXISTING,FILE_FLAG_WRITE_THROUGH,0);
    if (f == INVALID_HANDLE_VALUE) return 1;
    DWORD high;
    DWORD fsize = GetFileSize(f,&high);
    HANDLE m = CreateFileMapping(f,0,PAGE_WRITECOPY,0,0,0);
    offset_table* table = (offset_table*)MapViewOfFile(m,FILE_MAP_COPY,0,0,0);
    USHORT numTable = btols(table->numTables);
    table_record* record = (table_record*)(table+1);
    for (int i = 0; i < numTable; i++) {
        char* name = (char*)&record->tag;
        if (strnicmp(name,"gasp",4)==0) {
            ULONG offset = btoll(record->offset);
            ULONG length = btoll(record->length);
            gasp_table* gasp = (gasp_table*)((char*)table+offset);
            USHORT version = btols(gasp->version);
            USHORT numR = btols(gasp->numRanges);
            printf("gasp offset: 0x%x version:%d checksum: 0x%x real: 0x%x\n",offset,version,btoll(record->checkSum) ,CalcTableChecksum((ULONG*)gasp,length) );
            printf("chcksum offset: 0x%x\n",(char*)&record->checkSum-(char*)table);
            for (int j = 0; j < numR;  j++) {
                USHORT rangsmax = btols(gasp->gaspRange[j].rangeMaxPPEM);
                rangeGaspBehavior bhav = (rangeGaspBehavior)btols(gasp->gaspRange[j].rangeGaspBehavior);
                printf("%d:%d  0x%x %s\n",j,rangsmax,bhav,ap(bhav));
            }

        }
        else if (strnicmp(name,"head",4)==0) {
            ULONG offset = btoll(record->offset);
            ULONG length = btoll(record->length);
            head_table* head = (head_table*)((char*)table+offset);
            ULONG checksum = btoll(head->checkSumAdjustment);
            head->checkSumAdjustment = 0;
            record->checkSum = 0;
            ULONG allcheck = CalcTableChecksum((PULONG)table,fsize);
            int i = 0;
        }
        record++;
    }
	return 0;
}
